package com.hnas.sys.service.system;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.hnas.core.dao.PageBean;
import com.hnas.core.dto.DTOPagedList;
import com.hnas.core.exception.EntityNotFoundException;
import com.hnas.core.util.StringUtil;
import com.hnas.sys.dao.AuthorityDAO;
import com.hnas.sys.dao.AuthorityResourceDAO;
import com.hnas.sys.dao.MenuPackageDAO;
import com.hnas.sys.dao.ResourceDAO;
import com.hnas.sys.domain.ResourceStatus;
import com.hnas.sys.orm.Authority;
import com.hnas.sys.orm.AuthorityResource;
import com.hnas.sys.orm.MenuPackage;
import com.hnas.sys.orm.Resource;
import com.hnas.sys.service.system.criteria.DTOSearchResource;
import com.hnas.sys.service.system.criteria.ResourceCriterial;
import com.hnas.sys.service.system.data.DTOBackMenu;
import com.hnas.sys.service.system.data.DTOMenuItem;
import com.hnas.sys.service.system.dto.DTOAuthority;
import com.hnas.sys.service.system.dto.DTOMenuPackage;
import com.hnas.sys.service.system.dto.DTOResource;
import com.hnas.sys.service.system.dto.DTOUser;
import com.hnas.sys.service.system.mapper.MenuPackageMapper;
import com.hnas.sys.service.system.mapper.ResourceMapper;

/**
 * @author 郑兴(zhengxing)
 *
 */
@Component("resourceService")
@Transactional
public class ResourceServiceImpl implements ResourceService {
	@Autowired
	private ResourceDAO resourceDAO;
	@Autowired
	private AuthorityDAO authorityDAO;
	@Autowired
	private AuthorityResourceDAO authorityResourceDAO;
	@Autowired
	private MenuPackageDAO menuPackageDAO;
	/*
	 * (non-Javadoc)
	 * @see com.hna.dt.service.basic.ResourceService#save(com.hna.dt.service.basic.dto.DTOResource)
	 */
	public void saveOrUpdate(DTOResource resource, boolean excludeAuths) throws EntityNotFoundException{
//		if (null != resource) {
		String hql = "from Resource t where t.resource=?1";
		Resource rc = null;
			if (null == resource.getId() || resource.getId()==0) {
				List<	Resource> rcs = this.resourceDAO.findByQuery(hql, resource.getResource());
				if (rcs.size()>0){
					rc = rcs.get(0);
				}else{
					rc = new Resource();			
				}
				rc.setStatus(ResourceStatus.VALID);
//				resourceDAO.persist(rc);
			} else {
				 rc= this.resourceDAO.find(resource.getId());
				if (null == rc)
					return;
				
				rc.setStatus(ResourceStatus.VALID);
//				resourceDAO.merge(rc0);
		
			}
			BeanUtils.copyProperties(resource, rc, new String[] { "id" ,"status"});
			if(null==rc.getMenuPackageID()||rc.getMenuPackageID()==0 ){
				MenuPackage mpck = this.menuPackageDAO.getPackgeByName(resource.getPackgeName());
				if (null==mpck){
					throw new EntityNotFoundException("找不到菜单模块："+resource.getPackgeName());
				}
				rc.setMenuPackageID(mpck.getId());
			}
			if (!excludeAuths){
				Map<Long, AuthorityResource> map0 = new HashMap<Long, AuthorityResource>();
				for (AuthorityResource at : rc.getAuthorityResources()) {
					at.setResource(null);
					map0.put(at.getAuthority().getId(), at);
				}		
				
				rc.getAuthorityResources().clear();
			
				if (null!=resource.getRoleArr() && resource.getRoleArr().length>0){
					for (long id:resource.getRoleArr()){
						Authority aut = this.authorityDAO.find(id);//Long
						if (null == aut)
							continue;
	
						AuthorityResource arc = map0.get(aut.getId());
						if (null != arc) {
							if(arc.getResource()==null){
								arc.setResource(rc);
								rc.getAuthorityResources().add(arc);
							}
	//						map0.remove(aut.getId());
						} else {
							arc = new AuthorityResource();
							arc.setResource(rc);
							arc.setAuthority(aut);
							rc.getAuthorityResources().add(arc);
						}
					}
				}
				for (AuthorityResource ar:map0.values()){
					if (null==ar.getResource())
						this.authorityResourceDAO.remove(ar);
				}
			}
			if (rc.getId()>0)
				this.resourceDAO.merge(rc);
			else
				this.resourceDAO.persist(rc);
//		}
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.hna.dt.service.basic.ResourceService#delete(java.lang.Long)
	 */
	public void delete(Long id) {
		Resource resource = resourceDAO.find(id);
		if(null != resource) {
			resourceDAO.remove(resource);
		}
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.hna.dt.service.basic.ResourceService#load(java.lang.Long)
	 */
	@Transactional(readOnly=true,propagation=Propagation.REQUIRED)
	public DTOResource load(Long id) {
		Resource vo = resourceDAO.find(id);
		 DTOResource dto=ResourceMapper.getInstance().mapToValue(vo);
		 if (vo.getAuthorityResources().size()>0){
			 dto.setRoleArr(new long[vo.getAuthorityResources().size()]);
//			StringBuffer sb = new StringBuffer();
			int n=0;
			for (AuthorityResource ar:vo.getAuthorityResources()){
//				if (sb.length()>0)
//					sb.append(",");
//				sb.append(ar.getAuthority().getId());
				dto.getRoleArr()[n++]=ar.getAuthority().getId();
			}
//			sb.append(",");
//			dto.setRoles(","+sb.toString());
		 }
			return dto;
	}
	@Transactional(readOnly=true,propagation=Propagation.REQUIRED)
	public DTOResource get(Long id) {
		Resource vo = resourceDAO.find(id);
		 DTOResource dto=ResourceMapper.getInstance().mapToValue(vo);
		 return dto;
	}
	/*
	 * (non-Javadoc)
	 * @see com.hna.dt.service.basic.ResourceService#loadAllResource()
	 */
	@Transactional(readOnly=true,propagation=Propagation.REQUIRED)
	public List<DTOResource> loadAllResource() {
		return ResourceMapper.getInstance().mapToValues(resourceDAO.loadAll());
	}

	/*
	 * (non-Javadoc)
	 * @see com.hna.dt.service.system.ResourceService#queryResource(com.hna.dt.web.system.criteria.ResourceCriterial)
	 */
	@Transactional(readOnly=true,propagation=Propagation.REQUIRED)
	public List<DTOResource> queryResource(ResourceCriterial criterial) {
		return ResourceMapper.getInstance().mapToValues(resourceDAO.queryResource(criterial));
	}
	
	public List<DTOBackMenu> getUserMenus(DTOUser user) {
		// TODO Auto-generated method stub
		Long[] ids = new Long[user.getDtoAuthorities().size()];
		int i = 0;
		for (DTOAuthority at : user.getDtoAuthorities()) {
			ids[i++] = at.getId();
		}
		List<Resource> ls = this.resourceDAO.getResources(ids);
		Map<Long, List<DTOMenuItem>> map = new HashMap<Long, List<DTOMenuItem>>();
		Set<Long> rcs = new HashSet<Long>();
		for (Resource rc : ls) {
			if (rcs.contains(rc.getId()))
				continue;// 重复
			List<DTOMenuItem> value = map.get(rc.getMenuPackageID());
			if (value == null)
				value = new ArrayList<DTOMenuItem>();
			DTOResource dto = ResourceMapper.getInstance().mapToValue(rc);
			DTOMenuItem item = new DTOMenuItem();
			item.setResource(dto);
			value.add(item);
			map.put(rc.getMenuPackageID(), value);
			rcs.add(rc.getId());
		}
		Long[] ids2 = new Long[map.keySet().size()];
		i = 0;
		for (long id : map.keySet()) {
			ids2[i++] = id;
		}
		List<MenuPackage> ls2 = this.menuPackageDAO.loadPackageById(ids2);
		List<DTOMenuPackage> ls3 = MenuPackageMapper.getInstance().mapToValues(
				ls2);
		List<DTOBackMenu> menus = new ArrayList<DTOBackMenu>();
		for (DTOMenuPackage mu : ls3) {
//			mu.setResources(map.get(mu.getId()));
			DTOBackMenu menu = new DTOBackMenu();
			menu.setItems(map.get(mu.getId()));
			menu.setPack(mu);
			menu.setSelected(ls3.size()==1);
			menus.add(menu);
		}
		return menus;
	}
//	@Autowired
//	private MenuPackageDAO menuPackageDAO;
	public DTOPagedList<DTOResource> search(DTOSearchResource con) {
		// TODO Auto-generated method stub
//		return null;
		PageBean<Resource> page = new PageBean<Resource>();
		page.setPageNo(con.getPageNo());
		page.setPageSize(con.getPageSize());
		page.setTotalCount(con.getTotalCount());
		StringBuffer sb = new StringBuffer();
		List<String> paras = new ArrayList<String>();
		int j=1;
		sb.append(" and t.statusStr='VALID'");
		if (null!=con.getDto()){
		if (StringUtil.isNotEmpty(con.getDto().getName())) {
			sb.append(" and t.name like ?" + j++);
			paras.add("%"+con.getDto().getName().trim()+"%");
		}
		}
		if (sb.length() > 0) {
			sb.delete(0, 5);
			sb.insert(0, " from Resource t where ");
		} else {
			sb.append(" from Resource t");
		}
		page.setQuery(sb.toString());
		page.setQueryCount("select count(t.id) " + sb);
//		page.setQuery(sb.insert(" from Resource t".length(), " join fetch t.product ").toString());
		this.resourceDAO.queryByPage(page, paras.toArray());
		DTOPagedList<DTOResource> pageList = new DTOPagedList<DTOResource>();
		pageList.setPageNo(page.getPageNo());
		pageList.setPageSize(page.getPageSize());
		pageList.setTotalCount(page.getTotalCount());
		List<DTOResource> ls = new ArrayList<DTOResource>();
		for (Resource or : page.getList()) {
			DTOResource dto = new DTOResource();
			BeanUtils.copyProperties(or, dto, new String[]{"authorityResources"});
//			dto = ResourceMapper.getInstance().mapToValue(or);
			
			ls.add(dto);
		}
		pageList.setList(ls);
		return pageList;
	}

	public void disable(long id) {
		// TODO Auto-generated method stub
		Resource vo = this.resourceDAO.find(id);
		vo.setStatus(ResourceStatus.INVALID);
		this.resourceDAO.merge(vo);
	}

	public boolean hasResource(long userId, String resourceUrl) {
		// TODO Auto-generated method stub
		return this.resourceDAO.hasResource(userId, resourceUrl);
	}
}
